// #include <Arduino.h>

// // put function declarations here:
// int myFunction(int, int);

// void setup() {
//   // put your setup code here, to run once:
//   int result = myFunction(2, 3);
// }

// void loop() {
//   // put your main code here, to run repeatedly:
// }

// // put function definitions here:
// int myFunction(int x, int y) {
//   return x + y;
// }

//////////////////////////////////// DS18B20 温度传感器示例
// #include <Arduino.h>
// #include <OneWire.h>
// #include <DallasTemperature.h>
// #include <Adafruit_GFX.h>
// #include <Adafruit_SSD1306.h>
// #include <Wire.h>

// // 定义 DS18B20 数据引脚
// #define ONE_WIRE_BUS 23

// // 初始化 OneWire 和 DallasTemperature 库
// OneWire oneWire(ONE_WIRE_BUS);
// DallasTemperature sensors(&oneWire);

// // 初始化 OLED 屏幕（I2C 地址通常为 0x3C 或 0x3D）
// #define SCREEN_WIDTH 128
// #define SCREEN_HEIGHT 64
// #define OLED_RESET    -1 // 如果屏幕没有 RESET 引脚，设置为 -1
// #define SCREEN_ADDRESS 0x3C // I2C 地址

// Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// void setup() {
//   // 启动串口调试
//   Serial.begin(115200);

//   // 初始化 DS18B20
//   sensors.begin();
//   Serial.println("Initializing DS18B20...");

//   // 检查传感器是否连接
//   if (sensors.getDeviceCount() == 0) {
//     Serial.println("No DS18B20 sensors found!");
//   } else {
//     Serial.print("Found ");
//     Serial.print(sensors.getDeviceCount());
//     Serial.println(" DS18B20 sensors.");
//   }

//   // 初始化 I2C OLED 屏幕
//   if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
//     Serial.println(F("SSD1306 allocation failed"));
//     for (;;); // 如果初始化失败，停止程序
//   }

//   // 清空屏幕并设置默认字体
//   display.clearDisplay();
//   display.setTextSize(1);
//   display.setTextColor(SSD1306_WHITE);
//   display.setCursor(0, 0);
//   display.display();
// }

// void loop() {
//   // 请求温度数据
//   sensors.requestTemperatures();

//   // 读取温度
//   float temperature = sensors.getTempCByIndex(0);

//   // 如果温度为 -127°C，可能是传感器读取失败
//   if (temperature == -127) {
//     Serial.println("Error reading temperature from DS18B20!");
//   }

//   // 打印温度到串口
//   Serial.print("Temperature: ");
//   Serial.print(temperature);
//   Serial.println(" °C");

//   // 清空屏幕
//   display.clearDisplay();

//   // 显示温度数据
//   display.setCursor(0, 0);
//   display.print("Temperature:");
//   display.setCursor(0, 20);
//   display.print(temperature);
//   display.print(" ");
//   display.print((char)247); // 显示 ° 符号
//   display.print("C");

//   // 更新屏幕
//   display.display();

//   // 延迟 1 秒
//   delay(1000);
// }


///////////////////////////////////// DHT11 温湿度传感器示例
// #include <Arduino.h>
// #include <DHT.h>
// #include <Adafruit_GFX.h>
// #include <Adafruit_SSD1306.h>
// #include <Wire.h>

// // 定义 DHT11 数据引脚
// #define DHTPIN 23
// #define DHTTYPE DHT11

// // 初始化 DHT 传感器
// DHT dht(DHTPIN, DHTTYPE);

// // 初始化 OLED 屏幕（I2C 地址通常为 0x3C 或 0x3D）
// #define SCREEN_WIDTH 128
// #define SCREEN_HEIGHT 64
// #define OLED_RESET    -1 // 如果屏幕没有 RESET 引脚，设置为 -1
// #define SCREEN_ADDRESS 0x3C // I2C 地址

// Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// void setup() {
//   // 启动串口调试
//   Serial.begin(115200);

//   // 初始化 DHT11
//   dht.begin();
//   Serial.println("Initializing DHT11...");

//   // 初始化 OLED 屏幕
//   if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
//     Serial.println(F("SSD1306 allocation failed"));
//     for (;;); // 如果初始化失败，停止程序
//   }
  
//   display.setRotation(2); // 旋转 180 度

//   // 清空屏幕并设置默认字体
//   display.clearDisplay();
//   display.setTextSize(1);
//   display.setTextColor(SSD1306_WHITE);
//   display.setCursor(0, 0);
//   display.display();
// }

// void loop() {
//   // 读取湿度
//   float humidity = dht.readHumidity();
//   // 读取温度（摄氏度）
//   float temperature = dht.readTemperature();

//   // 检查是否读取成功
//   if (isnan(humidity) || isnan(temperature)) {
//     Serial.println("Failed to read from DHT11!");
//     return;
//   }

//   // 打印温湿度到串口
//   Serial.print("Humidity: ");
//   Serial.print(humidity);
//   Serial.print(" %\t");
//   Serial.print("Temperature: ");
//   Serial.print(temperature);
//   Serial.println(" °C");

//   // 清空屏幕
//   display.clearDisplay();

//   // 显示温湿度数据
//   display.setCursor(0, 0);
//   display.print("Humidity: ");
//   // Serial.begin(115200);
//   display.print(humidity);
//   display.print(" %");

//   display.setCursor(0, 20);
//   display.print("Temperature: ");
//   // Serial.begin(115200);
//   display.print(temperature);
//   display.print(" ");
//   display.print((char)247); // 显示 ° 符号
//   display.print("C");

//   // 更新屏幕
//   display.display();

//   // 延迟 2 秒（DHT11 的读取间隔至少为 1 秒）
//   delay(2000);
// }


////////////////////////////////////// ATGM336H GPS 示例
// #include <Arduino.h>
// #include <TinyGPS++.h>
// #include <Adafruit_GFX.h>
// #include <Adafruit_SSD1306.h>
// #include <Wire.h>
// #include <HardwareSerial.h>

// // 初始化 OLED 屏幕（I2C 地址通常为 0x3C 或 0x3D）
// #define SCREEN_WIDTH 128
// #define SCREEN_HEIGHT 64
// #define OLED_RESET    -1 // 如果屏幕没有 RESET 引脚，设置为 -1
// #define SCREEN_ADDRESS 0x3C // I2C 地址

// Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// // 初始化 GPS 对象
// TinyGPSPlus gps;

// // 定义 GPS 串口
// HardwareSerial GPSSerial(2); // 使用 ESP32 的 UART2（RX2: GPIO 16, TX2: GPIO 17）

// void setup() {
//   // 启动串口调试
//   Serial.begin(115200);

//   // 初始化 GPS 串口（ATGM336H 支持 9600 或 115200 波特率）
//   GPSSerial.begin(9600, SERIAL_8N1, 16, 17); // RX: 16, TX: 17
//   Serial.println("Initializing ATGM336H GPS...");

//   // 初始化 OLED 屏幕
//   if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
//     Serial.println(F("SSD1306 allocation failed"));
//     for (;;); // 如果初始化失败，停止程序
//   }

//   // 旋转屏幕 180 度（可选）
//   display.setRotation(2);

//   // 清空屏幕并设置默认字体
//   display.clearDisplay();
//   display.setTextSize(1);
//   display.setTextColor(SSD1306_WHITE);
//   display.setCursor(0, 0);
//   display.display();
// }

// void loop() {
//   // 读取 GPS 数据
//   while (GPSSerial.available() > 0) {
//     char c = GPSSerial.read();
//     char nmea[2] = { c, '\0' };
//     Serial.write(nmea); // 打印原始 NMEA 数据到串口
//     gps.encode(c); // 解析 GPS 数据
//   }

//   // 清空屏幕
//   display.clearDisplay();

//   // 检查是否有有效的 GPS 数据
//   if (gps.location.isValid()) {
//     // 显示纬度
//     display.setCursor(0, 0);
//     display.print("Lat: ");
//     display.print(gps.location.lat(), 6);

//     // 显示经度
//     display.setCursor(0, 10);
//     display.print("Lng: ");
//     display.print(gps.location.lng(), 6);

//     // 显示速度（km/h）
//     display.setCursor(0, 20);
//     display.print("Speed: ");
//     display.print(gps.speed.kmph());
//     display.print(" km/h");

//     // 显示日期和时间
//     display.setCursor(0, 30);
//     display.print("Date: ");
//     if (gps.date.isValid()) {
//       display.print(gps.date.year());
//       display.print("-");
//       display.print(gps.date.month());
//       display.print("-");
//       display.print(gps.date.day());
//     } else {
//       display.print("Invalid");
//     }

//     display.setCursor(0, 40);
//     display.print("Time: ");
//     if (gps.time.isValid()) {
//       display.print(gps.time.hour());
//       display.print(":");
//       display.print(gps.time.minute());
//       display.print(":");
//       display.print(gps.time.second());
//     } else {
//       display.print("Invalid");
//     }

//     // 显示卫星数量
//     display.setCursor(0, 50);
//     display.print("Sats: ");
//     display.print(gps.satellites.value());
//   } else {
//     // 如果没有有效的 GPS 数据，显示卫星数量和提示信息
//     display.setCursor(0, 0);
//     display.print("Searching for GPS...");

//     // 显示卫星数量
//     display.setCursor(0, 10);
//     display.print("Sats: ");
//     display.print(gps.satellites.value());

//     // 显示提示信息
//     display.setCursor(0, 20);
//     display.print("Move to open area");
//   }

//   // 更新屏幕
//   display.display();

//   // 延迟 1 秒
//   delay(1000);
// }

// $GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47
// $GPRMC,123519,A,4807.038,N,01131.000,E,022.4,084.4,230394,003.1,W*6A


////////////////////////////////////// 温湿度计 与 ATGM336H GPS 示例
// #include <Arduino.h>
// #include <TinyGPS++.h>
// #include <DHT.h>
// #include <Adafruit_GFX.h>
// #include <Adafruit_SSD1306.h>
// #include <Wire.h>
// #include <HardwareSerial.h>

// // 定义 DHT11 数据引脚
// #define DHTPIN 23
// #define DHTTYPE DHT11

// // 初始化 DHT 传感器
// DHT dht(DHTPIN, DHTTYPE);

// // 初始化 OLED 屏幕（I2C 地址通常为 0x3C 或 0x3D）
// #define SCREEN_WIDTH 128
// #define SCREEN_HEIGHT 64
// #define OLED_RESET    -1 // 如果屏幕没有 RESET 引脚，设置为 -1
// #define SCREEN_ADDRESS 0x3C // I2C 地址

// Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// // 初始化 GPS 对象
// TinyGPSPlus gps;

// // 定义 GPS 串口
// HardwareSerial GPSSerial(2); // 使用 ESP32 的 UART2（RX2: GPIO 16, TX2: GPIO 17）

// // 定义显示模式切换时间
// unsigned long lastSwitchTime = 0;
// bool showDHTData = true; // 当前显示模式（true: 温湿度数据，false: GPS 数据）

// void setup() {
//   // 启动串口调试
//   Serial.begin(115200);

//   // 初始化 DHT11
//   dht.begin();
//   Serial.println("Initializing DHT11...");

//   // 初始化 GPS 串口
//   GPSSerial.begin(9600, SERIAL_8N1, 16, 17); // RX: 16, TX: 17
//   Serial.println("Initializing ATGM336H GPS...");

//   // 初始化 OLED 屏幕
//   if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
//     Serial.println(F("SSD1306 allocation failed"));
//     for (;;); // 如果初始化失败，停止程序
//   }

//   // 旋转屏幕 180 度（可选）
//   display.setRotation(2);

//   // 清空屏幕并设置默认字体
//   display.clearDisplay();
//   display.setTextSize(1);
//   display.setTextColor(SSD1306_WHITE);
//   display.setCursor(0, 0);
//   display.display();
// }

// void displayDHTData();
// void displayGPSData();
// void loop() {
//   // 读取 GPS 数据
//   while (GPSSerial.available() > 0) {
//     gps.encode(GPSSerial.read()); // 解析 GPS 数据
//   }

//   // 每 3 秒切换显示模式
//   if (millis() - lastSwitchTime >= 3000) {
//     showDHTData = !showDHTData; // 切换显示模式
//     lastSwitchTime = millis(); // 更新切换时间
//   }

//   // 清空屏幕
//   display.clearDisplay();

//   if (showDHTData) {
//     // 显示温湿度数据
//     displayDHTData();
//   } else {
//     // 显示 GPS 数据
//     displayGPSData();
//   }

//   // 更新屏幕
//   display.display();

//   // 延迟 1 秒
//   delay(1000);
// }

// void displayDHTData() {
//   // 读取湿度
//   float humidity = dht.readHumidity();
//   // 读取温度（摄氏度）
//   float temperature = dht.readTemperature();

//   // 检查是否读取成功
//   if (isnan(humidity) || isnan(temperature)) {
//     display.setCursor(0, 0);
//     display.print("Failed to read DHT11!");
//     return;
//   }

//   // 显示湿度
//   display.setCursor(0, 0);
//   display.print("Humidity: ");
//   display.print(humidity);
//   display.print(" %");

//   // 显示温度
//   display.setCursor(0, 10);
//   display.print("Temperature: ");
//   display.print(temperature);
//   display.print(" ");
//   display.print((char)247); // 显示 ° 符号
//   display.print("C");
// }

// void displayGPSData() {
//   // 检查是否有有效的 GPS 数据
//   if (gps.location.isValid()) {
//     // 显示纬度
//     display.setCursor(0, 0);
//     display.print("Lat: ");
//     display.print(gps.location.lat(), 6);

//     // 显示经度
//     display.setCursor(0, 10);
//     display.print("Lng: ");
//     display.print(gps.location.lng(), 6);

//     // 显示速度（km/h）
//     display.setCursor(0, 20);
//     display.print("Speed: ");
//     display.print(gps.speed.kmph());
//     display.print(" km/h");

//     // 显示卫星数量
//     display.setCursor(0, 30);
//     display.print("Sats: ");
//     display.print(gps.satellites.value());
//   } else {
//     // 如果没有有效的 GPS 数据，显示提示信息
//     display.setCursor(0, 0);
//     display.print("Searching for GPS...");

//     // 显示卫星数量
//     display.setCursor(0, 10);
//     display.print("Sats: ");
//     display.print(gps.satellites.value());

//     // 显示提示信息
//     display.setCursor(0, 20);
//     display.print("Move to open area");
//   }
// }

////////////////////////////////////// WIFI 连接 示例代码
// #include <Arduino.h>
// #include <WiFi.h>

// #define WIFI_SSID "xxx"
// #define WIFI_PASS "xxx"

// #define ONE_LED
// #define LED_BUILTIN 2

// void setup() { 
//   Serial.begin(115200);
//   WiFi.begin(WIFI_SSID, WIFI_PASS);
//   Serial.println("Connecting to WiFi...");

//   #ifdef ONE_LED
//     pinMode(LED_BUILTIN, OUTPUT);
//     digitalWrite(LED_BUILTIN, LOW);
//   #endif

//   while (WiFi.status() != WL_CONNECTED) {
//     delay(500);
//     Serial.print(".");
//   }
//   Serial.println("");
//   Serial.println("WiFi connected");

//   Serial.println("IP address: ");
//   Serial.println(WiFi.localIP());
//   delay(1000);

//   #ifdef ONE_LED
//     digitalWrite(LED_BUILTIN, HIGH);
//   #endif
// }

// void loop() { 
//   Serial.print(".");
//   delay(500);
// }

////////////////////////////////////// WIFI 连接 MQTT 示例代码
#include <Arduino.h>
#include <WiFi.h>
#include <PubSubClient.h>

#define WIFI_SSID "xxx"
#define WIFI_PASS "xxx"

#define ONE_LED
#define LED_BUILTIN 2

#define MQTT_SERVER "x.x.x.x"
#define MQTT_PORT   1883
#define MQTT_TOPIC  "your/topic"

void blink() {
  digitalWrite(LED_BUILTIN, HIGH);
  delay(100);
  digitalWrite(LED_BUILTIN, LOW);
  delay(100);
}

char msg[128];

void topic(char *topic, byte *payload, unsigned int length) {
  // Serial.print("Message arrived [");
  // Serial.print(topic);
  // Serial.print("] ");

  // 判断是否是订阅的 Topic
  if (strcmp(topic, MQTT_TOPIC) == 0) {
    // [1]
    // Serial.println("Received message from MQTT server.");
    // for (int i = 0; i < length; i++) {
    //   Serial.print((char)payload[i]);
    // }
    // Serial.println();

    // [2]
    // msg
    snprintf(msg, sizeof(msg), "%.*s", length, payload);
    Serial.println(msg);

    blink();
  }
}

WiFiClient espClient;
PubSubClient client(espClient);

void setup() { 
  Serial.begin(115200);

  WiFi.begin(WIFI_SSID, WIFI_PASS);
  Serial.println("Connecting to WiFi...");

  #ifdef ONE_LED
    pinMode(LED_BUILTIN, OUTPUT);
    digitalWrite(LED_BUILTIN, LOW);
  #endif

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.println("WiFi connected");

  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  delay(1000);

  #ifdef ONE_LED
    digitalWrite(LED_BUILTIN, HIGH);
  #endif

  client.setServer(MQTT_SERVER, MQTT_PORT);
  client.setCallback(topic);
}

void loop() { 
  // Serial.print(".");

  if (!client.connected()) {
    Serial.println("Connecting to MQTT...");
    if (client.connect("ESP32Client")) {
      Serial.println("Connected to MQTT.");
      client.subscribe(MQTT_TOPIC);
    } else {
      Serial.print("Failed to connect to MQTT, rc=");
      Serial.println(client.state());
      delay(5000);
    }
  } else {
    client.loop();
  }

  delay(500);
}
